// Copyright (C) Kumo inc. and its affiliates.
// Author: Jeff.li lijippy@163.com
// All rights reserved.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero General Public License as published
// by the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program.  If not, see <https://www.gnu.org/licenses/>.
//


#include <pollux/dwio/common/bit_concatenation.h>

#include <gtest/gtest.h>

using namespace kumo::pollux;
using namespace kumo::pollux::dwio::common;

TEST(BitConcatenationTests, basic) {
  memory::MemoryManager::testingSetInstance({});
  auto pool = kumo::pollux::memory::memoryManager()->addLeafPool();
  BitConcatenation bits(*pool);
  BufferPtr result;

  std::vector<uint64_t> oneBits(10, ~0UL);
  std::vector<uint64_t> zeroBits(10, 0UL);

  // add only one bits, expect nullptr.
  bits.reset(result);
  bits.appendOnes(34);
  bits.append(oneBits.data(), 3, 29);
  EXPECT_EQ(34 + (29 - 3), bits.numBits());
  EXPECT_TRUE(!result);
  EXPECT_TRUE(!bits.buffer());

  // Add ones, then zeros and then ones. Expect bitmap.
  bits.reset(result);
  bits.append(oneBits.data(), 0, 29);
  bits.append(zeroBits.data(), 3, 29);
  bits.append(oneBits.data(), 6, 29);
  // Expecting  29 ones, 26 zeros and 23 zeros.
  EXPECT_EQ(29 + 26 + 23, bits.numBits());
  auto data = result->as<uint64_t>();
  EXPECT_TRUE(bits::isAllSet(data, 0, 29, true));
  EXPECT_TRUE(bits::isAllSet(data, 29, 29 + 26, false));
  EXPECT_TRUE(bits::isAllSet(data, 29 + 26, 29 + 26 + 23, true));

  // Add only one bits, expect nullptr, even though 'result' has a value.
  bits.reset(result);
  bits.appendOnes(24);
  bits.append(oneBits.data(), 3, 29);
  EXPECT_EQ(24 + (29 - 3), bits.numBits());
  EXPECT_TRUE(!bits.buffer());
  EXPECT_FALSE(!result);
}
